package com.jgc.stage02.同步工具类;

import org.junit.Test;

import java.util.concurrent.CyclicBarrier;

/**
 * Created by Administrator on 2022/2/11.
 * CyclicBarrier 循环栅栏 [saɪklɪk][bæriə(r)]
 * 它的作用就是会让所有线程都等待完成后才会继续下一步行动
 * 就像生活中我们会约朋友们到某个餐厅一起吃饭，有些朋友可能会早到，有些朋友可能会晚到，
 * 但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程，餐厅就是 CyclicBarrier
 *  构造方法有以下2个
 * public CyclicBarrier(int parties)
   public CyclicBarrier(int parties, Runnable barrierAction)
   parties 是参与线程的个数 第二个构造方法有一个 Runnable 参数，这个参数的意思是最后一个到达线程要做的任务

   线程调用 await() 表示自己已经到达栅栏
 BrokenBarrierException 表示栅栏已经被破坏，破坏的原因可能是其中一个线程 await() 时被中断或者超时

 CyclicBarrier 可以用于多线程计算数据，最后合并计算结果的场景
 CountDownLatch 是一次性的，CyclicBarrier 是可循环利用的
 */
public class TestCyclicBarrier {

    //需要实现 一个线程组的线程需要等待所有线程完成任务后再继续执行下一次任务
    public static void main(String[] args) {
        test01();
        test02();//最后完成需要做事情
    }
    public static void test01(){
        int threadNum = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum);
        for(int i=0;i<5;i++){
            new TaskThread(cyclicBarrier).start();
        }
    }

    public static void test02(){
        int threadNum = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum, new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 是完成最后任务的线程");
            }
        });
        for(int i=0;i<5;i++){
            new TaskThread(cyclicBarrier).start();
        }
    }
    static class TaskThread extends Thread{
        CyclicBarrier barrier;
        public TaskThread(CyclicBarrier cyclicBarrier) {
            this.barrier = cyclicBarrier;
        }
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(getName() + " 到达栅栏 A");
                barrier.await();
                System.out.println(getName() + " 冲破栅栏 A");
                Thread.sleep(2000);
                System.out.println(getName() + " 到达栅栏 B");
                barrier.await();
                System.out.println(getName() + " 冲破栅栏 B");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
